#include "liveinfoview.h"
#include "libs/core/model/livemodel.h"
#include "libs/core/model/model.h"
#include "useragentgenerator.h"
#include "widgets/web/webbridge.h"
#include "widgets/web/webinterface.h"
#include "widgets/web/webpage.h"
#include "widgets/web/webview.h"
#include "yingce.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QtDebug>
#include <QVBoxLayout>
#include <QWebChannel>
#include <QWebEngineCookieStore>
#include <QWebEngineProfile>
#include <QWebEngineScript>
#include <QWebEngineScriptCollection>
#include <QWebEngineSettings>

LiveInfoView::LiveInfoView(const QString& name, QWidget* parent) : QWidget { parent }, name_(name)
{
    QVBoxLayout* vl = new QVBoxLayout(this);
    vl->setContentsMargins(0, 0, 0, 0);
    vl->setSpacing(0);

    profile_ = new QWebEngineProfile(this);
    profile_->setHttpCacheType(QWebEngineProfile::DiskHttpCache);
    profile_->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);
    profile_->setHttpAcceptLanguage("zh-CN,zh;q=0.9,en;q=0.8");
    // 清除所有痕迹
    profile_->clearAllVisitedLinks();
    profile_->clearHttpCache();
    profile_->cookieStore()->deleteAllCookies();

    page_ = new WebPage(profile_, this);
    if (QWebEngineSettings* settings = page_->settings()) {
        settings->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, false);
        settings->setAttribute(QWebEngineSettings::AutoLoadImages, true);
        settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, false);
        settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, false);
        settings->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, false);
        settings->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
        settings->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, false);
        settings->setAttribute(QWebEngineSettings::JavascriptCanPaste, false);
        settings->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
        settings->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, false);
        settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true);
        settings->setAttribute(QWebEngineSettings::PluginsEnabled, true);
        settings->setAttribute(QWebEngineSettings::WebGLEnabled, true);
        settings->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled, true);
    }

    web_view_ = new WebView(this);
    web_view_->setPage(page_);
    // // 设置显示比例为1.0，模拟移动端环境
    // web_view_->setZoomFactor(1.0);
    web_view_->setContextMenuPolicy(Qt::NoContextMenu);
    vl->addWidget(web_view_, 1);

    BridgeObjectManager* obj_mgr = YingCe::instance()->bridgeObjectManager();
    WebInterface* interface = new ClientWebInterface(page_, this);
    WebBridge* bridge = new WebBridge(this, page_, interface, obj_mgr, this);

    // WebChannel
    QWebChannel* channel = new QWebChannel(this);
    channel->registerObject(obj_mgr->frameworkName(), bridge);
    page_->setWebChannel(channel);

    BridgeObject bo;
    bo.registerMethod("setLiveInfo", BridgeMethod(this, &LiveInfoView::setLiveInfo));
    bo.registerMethod("setCaptcha", BridgeMethod(this, &LiveInfoView::setCaptcha));
    obj_mgr->registerObject(name, bo);

    bridge->inject(obj_mgr->frameworkName(), WebBridge::genScriptName());

    connect(page_, &WebPage::loadFinished, this, [this](bool ok) {
        if (!ok && !handled_) {
            handler_(presenter_, QString());
            handled_ = true;
        }
    });

    timer_ = new QTimer(this);
    timer_->setInterval(10000);
    timer_->setSingleShot(false);
    connect(timer_, &QTimer::timeout, this, [this] {
        if (!handled_) {
            handled_ = true;
            handler_(presenter_, QString());
        }
        presenter_ = 0;
        // web_view_->load(QUrl { "about:blank" });
    });
}

LiveInfoView::~LiveInfoView()
{
    delete web_view_;
    delete page_;
    delete profile_;
}

void LiveInfoView::getLiveInfo(int presenter, int platform, const QString& presenter_platform_id,
                               int timeout, const LiveHandler& handler)
{
    const auto entry = YingCe::instance()->model()->liveModel()->webEntry(platform);
    if (!entry.url.isEmpty()) {
        presenter_ = presenter;
        handler_ = handler;
        handled_ = false;

        // 设置UserAgent
        profile_->setHttpUserAgent(UserAgentGenerator::getUserAgent(
                QString("%1,%2").arg(name_).arg(platform_), entry.ua));

        // 更换脚本
        if (platform_ != platform) {
            // 删除老的脚本
            QWebEngineScriptCollection& collection = page_->scripts();
            const auto scripts =
                    collection.find(QString::fromLatin1("yc.liveinfo.script_%1").arg(platform_));
            for (const auto& i : scripts) {
                collection.remove(i);
            }

            // 注入新脚本
            if (!entry.script.source_code.isEmpty()) {
                QWebEngineScript::InjectionPoint point = QWebEngineScript::InjectionPoint::Deferred;
                if (entry.script.injection_point == 1) {
                    point = QWebEngineScript::InjectionPoint::DocumentCreation;
                } else if (entry.script.injection_point == 2) {
                    point = QWebEngineScript::InjectionPoint::DocumentReady;
                }
                WebBridge::injectScript(*page_, entry.script.source_code.arg(name_).arg(0),
                                        QString::fromLatin1("yc.liveinfo.script_%1").arg(platform),
                                        QWebEngineScript::MainWorld, point);
            }

            // 保存新的平台类型
            platform_ = platform;
        }

        // 启动超时定时器
        timer_->start(timeout);

        // 加载页面
        web_view_->load(QUrl { entry.url.arg(presenter_platform_id) });
    }
}

void LiveInfoView::unload()
{
    timer_->stop();
    presenter_ = 0;
    handled_ = true;
    web_view_->load(QUrl { "about:blank" });
}

QString LiveInfoView::setLiveInfo(const QString& args, const QString& success_callback,
                                  const QString& failure_callback, const QString& sender_id,
                                  QWidget* sender_view)
{
    Q_UNUSED(success_callback)
    Q_UNUSED(failure_callback)
    Q_UNUSED(sender_id)
    Q_UNUSED(sender_view)

    // QFile file("e:/douyin.json");
    // if (file.open(QFile::WriteOnly | QFile::Truncate)) {
    //     file.write(args.toUtf8());
    //     file.close();
    // }

    timer_->stop();

    if (captcha_shown_ && !args.isEmpty()) {
        captcha_shown_ = false;
        if (!passed_captcha_) {
            passed_captcha_ = true;
            Q_EMIT captchaStateChanged(true);
        }
    }

    if (!handled_) {
        handled_ = true;
        handler_(presenter_, args);
    }

    if (!args.isEmpty()) {
        qDebug() << "LiveInfoView: failed to get live info" << presenter_ << platform_;
    }

    return QString();
}

QString LiveInfoView::setCaptcha(const QString& args, const QString& success_callback,
                                 const QString& failure_callback, const QString& sender_id,
                                 QWidget* sender_view)
{
    Q_UNUSED(args)
    Q_UNUSED(success_callback)
    Q_UNUSED(failure_callback)
    Q_UNUSED(sender_id)
    Q_UNUSED(sender_view)
    qCritical() << "LiveInfoView required captcha.";
    timer_->stop();
    captcha_shown_ = true;
    passed_captcha_ = false;
    Q_EMIT captchaStateChanged(false);
    return QString();
}
